package com.university.evaluation.utils;

import com.university.evaluation.entity.User;
import com.university.evaluation.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Objects;
import java.util.Random;

@Component
public class SecurityUtils {

    private static UserService userService;

    @Autowired
    public SecurityUtils(UserService userService) {
        SecurityUtils.userService = userService;
    }

    private static final BCryptPasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
    private static final Random RANDOM = new Random();
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    // 加密密码
    public static String encodePassword(String rawPassword) {
        return PASSWORD_ENCODER.encode(rawPassword);
    }

    // 验证密码
    public static boolean matchesPassword(String rawPassword, String encodedPassword) {
        return PASSWORD_ENCODER.matches(rawPassword, encodedPassword);
    }

    // 生成随机密码
    public static String generateRandomPassword(int length) {
        if (length <= 0) {
            throw new IllegalArgumentException("密码长度必须大于0");
        }
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(CHARACTERS.charAt(RANDOM.nextInt(CHARACTERS.length())));
        }
        return sb.toString();
    }

    // 获取当前登录用户的认证信息
    public static Authentication getCurrentAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    // 获取当前登录用户的用户名
    public static String getCurrentUsername() {
        Authentication authentication = getCurrentAuthentication();
        if (authentication != null && authentication.isAuthenticated()) {
            return authentication.getName();
        }
        return null;
    }

    // 获取当前登录用户对象
    public static User getCurrentUser() {
        String username = getCurrentUsername();
        if (username != null && userService != null) {
            return userService.findByUsername(username);
        }
        return null;
    }

    // 检查当前用户是否具有指定权限
    public static boolean hasAuthority(String authority) {
        Authentication authentication = getCurrentAuthentication();
        if (authentication != null && authentication.isAuthenticated() && 
            authentication.getPrincipal() instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            return userDetails.getAuthorities().stream()
                    .anyMatch(auth -> Objects.equals(auth.getAuthority(), authority));
        }
        return false;
    }

    // 检查当前用户是否具有指定角色
    public static boolean hasRole(String role) {
        // 角色在Spring Security中通常以ROLE_前缀存储
        return hasAuthority("ROLE_" + role);
    }

    // 检查当前用户是否为管理员
    public static boolean isAdmin() {
        User currentUser = getCurrentUser();
        if (currentUser != null) {
            // 假设角色ID为1表示管理员
            return Objects.equals(currentUser.getRoleId(), 1L);
        }
        return false;
    }

    // 检查当前用户是否为指定ID的用户或管理员
    public static boolean isCurrentUserOrAdmin(Long userId) {
        User currentUser = getCurrentUser();
        if (currentUser != null) {
            return Objects.equals(currentUser.getId(), userId) || isAdmin();
        }
        return false;
    }

    // 检查当前用户是否已认证
    public static boolean isAuthenticated() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication != null && authentication.isAuthenticated() && 
               !(authentication.getPrincipal() instanceof String && "anonymousUser".equals(authentication.getPrincipal()));
    }

    // 生成MD5哈希值
    public static String generateMD5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(input.getBytes());
            BigInteger no = new BigInteger(1, messageDigest);
            String hashtext = no.toString(16);
            while (hashtext.length() < 32) {
                hashtext = "0" + hashtext;
            }
            return hashtext;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5算法不可用", e);
        }
    }

    // 生成SHA-256哈希值
    public static String generateSHA256(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] messageDigest = md.digest(input.getBytes());
            BigInteger no = new BigInteger(1, messageDigest);
            String hashtext = no.toString(16);
            while (hashtext.length() < 64) {
                hashtext = "0" + hashtext;
            }
            return hashtext;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256算法不可用", e);
        }
    }

    // 生成随机盐值
    public static String generateSalt(int length) {
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(CHARACTERS.charAt(RANDOM.nextInt(CHARACTERS.length())));
        }
        return sb.toString();
    }

    // 使用盐值加密密码
    public static String encryptWithSalt(String password, String salt) {
        return generateSHA256(password + salt);
    }

    // Base64编码
    public static String encodeBase64(byte[] data) {
        return Base64.getEncoder().encodeToString(data);
    }

    // Base64解码
    public static byte[] decodeBase64(String encoded) {
        return Base64.getDecoder().decode(encoded);
    }

    // 生成随机token
    public static String generateToken(int length) {
        return generateRandomPassword(length);
    }

    // 隐藏敏感信息，如手机号码、身份证号码等
    public static String maskSensitiveInfo(String info, int startShow, int endShow) {
        if (info == null || info.length() <= startShow + endShow) {
            return info;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(info.substring(0, startShow));
        for (int i = startShow; i < info.length() - endShow; i++) {
            sb.append('*');
        }
        sb.append(info.substring(info.length() - endShow));
        return sb.toString();
    }

    // 隐藏手机号码中间四位
    public static String maskPhoneNumber(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.length() != 11) {
            return phoneNumber;
        }
        return maskSensitiveInfo(phoneNumber, 3, 4);
    }

    // 隐藏身份证号码中间八位
    public static String maskIdCardNumber(String idCardNumber) {
        if (idCardNumber == null || (idCardNumber.length() != 15 && idCardNumber.length() != 18)) {
            return idCardNumber;
        }
        if (idCardNumber.length() == 15) {
            return maskSensitiveInfo(idCardNumber, 6, 3);
        } else {
            return maskSensitiveInfo(idCardNumber, 6, 4);
        }
    }

    // 隐藏邮箱地址
    public static String maskEmail(String email) {
        if (email == null || !StringUtils.isValidEmail(email)) {
            return email;
        }
        int atIndex = email.indexOf('@');
        if (atIndex <= 2) {
            // 如果用户名太短（小于等于2个字符），则直接返回原邮箱
            return email;
        }
        String username = email.substring(0, atIndex);
        String domain = email.substring(atIndex);
        
        // 用户名长度
        int usernameLength = username.length();
        
        // 根据用户名长度决定中间星号的数量
        StringBuilder maskedUsername = new StringBuilder();
        maskedUsername.append(username.charAt(0)); // 保留第一个字符
        
        // 中间用星号替换
        if (usernameLength <= 4) {
            // 用户名较短时，使用1个星号
            maskedUsername.append('*');
        } else {
            // 用户名较长时，使用更多星号，但不超过用户名长度-2
            int asteriskCount = Math.min(usernameLength - 2, 8);
            for (int i = 0; i < asteriskCount; i++) {
                maskedUsername.append('*');
            }
        }
        
        maskedUsername.append(username.charAt(usernameLength - 1)); // 保留最后一个字符
        
        return maskedUsername.toString() + domain;
    }

    // 检查字符串是否包含敏感词
    public static boolean containsSensitiveWords(String text, String[] sensitiveWords) {
        if (text == null || sensitiveWords == null || sensitiveWords.length == 0) {
            return false;
        }
        for (String word : sensitiveWords) {
            if (text.contains(word)) {
                return true;
            }
        }
        return false;
    }

}